<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */
declare (strict_types=1);

namespace app\shop_admin\service;

use app\index\util\CreateNo;
use app\madmin\model\Configuration;
use app\madmin\model\PayMode;
use app\shop_admin\model\Order;
use app\shop_admin\model\UserCash;
use think\Exception;
use WePay\Refund;

class PaymentService
{

    private $options;
    private $trade;

    public function __construct()
    {
        $this->trade = CreateNo::buildTransfersNo();
    }


//    public function __construct()
//    {
//        if (Cache::has('WXPAY:OPTIONS')) {
//            $this->options = Cache::get('WXPAY:OPTIONS');
//        }
//        else {
//            $this->options = PayMode::find(['status' => 1])->toArray();
//            if (empty($this->options))
//                throw new Exception("请配置微信参数", HTTP_SERVERERROR);
//            Cache::set('WXPAY:OPTIONS', $this->options, 0);
//        }
//    }


    /**
     * 订单退款
     * @param $orderId int 订单编号
     * @param array $refundData .notify_url string 退款回调地址
     * @return array|bool
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function refund(int $orderId, array $refundData)
    {
        if (!isset($refundData['refund']) || empty($refundData['refund'])){
            return true;
        }
        $order = Order::find($orderId);

        switch ($order->base_in) {
            case "wechat":
                $method = "wx";
                break;
            case "wechata":
                $method = "wx";
                break;
            default:
                $method = "wx";
                break;
        }

        switch ((int)$order->getData("pay_id")) {
            case 1:
                $res = $this->rechargeRefund($order, $refundData);
                break;
            case 2:
                $this->getOptions($order->base_in, $method);
                $res = $this->wechatRefund($order, $refundData);
                break;
            case 3:
                $this->getOptions($order->base_in, $method);
                $res = $this->aliRefund($order, $refundData);
                break;
        }
        return $res;
    }

    /**
     * 退款至余额
     * @param $order
     * @param $refundData
     * @return bool
     */
    private function rechargeRefund($order, $refundData)
    {
        UserCash::where('user_id', $order->user_id)
            ->inc('total', $refundData['refund'])
            ->dec('expense', $refundData['refund'])
            ->update();
        return true;
    }

    /**
     * 退款至微信钱包
     * @param $order
     * @param $refundData
     * @return array
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     */
    private function wechatRefund($order, $refundData)
    {
        $jsapiOptions = $this->getJsapiOptions();

        $data = [
            "out_trade_no" => $order->unified_order_no,
            "out_refund_no" => "refund_" . CreateNo::msectime() . $order->user_id,
            "total_fee" => bcmul((string)$order->unified_money, (string)100, 0),
            "refund_fee" => bcmul((string)$refundData['refund'], (string)100, 0),
//            "refund_desc" => $refundData['desc'],
//            "notify_url" => $refundData['notify_url'],
        ];

        $refund = new Refund($jsapiOptions);
        return $refund->create($data);
    }

    /**
     * 退款至支付宝
     * @param $order
     * @param $refundData
     * @return bool
     */
    private function aliRefund($order, $refundData)
    {

        return true;
    }


    /**
     * 获取jsapiOptions
     * @return array
     */
    private function getJsapiOptions()
    {


        $data=[
            "appid" => $this->options['configuration']['AppId'],
            "mch_id" => $this->options['configuration']['MchId'],
            "mch_key" => $this->options['configuration']['APIKEY'],
            "ssl_key" => root_path(). "runtime/" . $this->options['wxkey'],
            "ssl_cer" => root_path(). "runtime/" . $this->options['cert']
        ];
        if ($this->options['type']==2){
            $data['sub_appid']=$this->options['configuration']['M_AppId'] ?? '';
            $data['sub_mch_id']=$this->options['configuration']['M_MchId'] ?? '';
        }
        return $data;
    }

    /**
     * 获取微信参数
     * @param $baseIn
     * @param $method
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    private function getOptions($baseIn, $method)
    {

        $configuration = Configuration::where(['type' => "mallPayMode"])->value("configuration");

        if (empty($configuration))
            throw new Exception("未完善支付配置");
        $configuration = json_decode($configuration, true);
        if (empty($configuration[$baseIn][$method]))
            throw new Exception("未开启支付配置");
        if (in_array($method, ['wx', 'ali'])) {
            $options = PayMode::find($configuration[$baseIn][$method . "_pay_mode_id"]);
            if (!$options)
                throw new Exception("未配置支付模板");
            $this->options = $options->toArray();
        }
    }

}